import java.util.ArrayList;
import java.util.List;

import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.ParseTree;
// org.antlr.v4.runtime.tree.ParseTree
import org.antlr.v4.runtime.tree.TerminalNode;

// TODO: change to listener

public class ExpressionHandler extends GoParserBaseVisitor<Integer> {

    enum Operations{
        id, uminus, mul, plus, sub
    }

    class Line{
        public int idx;
        public Operations op;
        public String arg1, arg2;
        public ParserRuleContext ctx;

        public Line(int idx, Operations op, String arg1, String arg2, ParserRuleContext ctx){
            this.idx = idx;
            this.op = op;
            this.arg1 = arg1;
            this.arg2 = arg2;
            this.ctx = ctx;
            System.out.println("New Line: " + this.toString());
        }

        @Override
        public String toString() {
            // TODO Auto-generated method stub
            // System.out.println(idx + " | " + this.op + " | " + arg1 + " | " + arg2 + " | " + ctx);
            // return super.toString();
            String res = idx + " | " + this.op + " | " + arg1 + " | " + arg2 + " | " + ctx + " | " + ctx.getText() + "\n";
            return res;
        }
    }

    class Table {

        public ArrayList<Line> table = new ArrayList<Line>();
        public int size = 0;

        @Override
        public String toString() {
            // TODO Auto-generated method stub
            String res = "";
            for (int i = 0; i < table.size(); i ++){
                res += table.get(i).toString();
            }
            return res;
        }

        public void add(Line line){
            table.add(line);
            size ++;
        }
    };

    public int getRef(ParserRuleContext ctx){
        int ref = 0;
        for (; ref < table.size; ref ++){
            if(table.table.get(ref).ctx == ctx){
                System.out.println("InTable: " + table.table.get(ref).ctx + "  " + table.table.get(ref).ctx.getText());
                System.out.println("Target : " + ctx + "  " + ctx.getText());
                break;
            }
        }
        return ref;
    }

    Table table = new Table();
    
    public Integer visitExpression(GoParser.ExpressionContext ctx){
        if(ctx.unary_op != null){
            ParserRuleContext child = ctx.expression(0);
            Line line = new Line(table.size, Operations.uminus, Integer.toString(getRef(child)), null, ctx);
            table.add(line);
            // System.out.println(table);
        }
        else if(ctx.mul_op != null){
            // TerminalNode token = ctx.primaryExpr().operand().operandName().IDENTIFIER();
            // Line line = new Line(table.size, Operations.mul, token.getText(), null, ctx);
            // table.add(line);
        }
        else if(ctx.add_op != null){
            // TerminalNode token = ctx.primaryExpr().operand().operandName().IDENTIFIER();
            // Line line = new Line(table.size, Operations.plus, token.getText(), null, ctx);
            // table.add(line);
        }
        else if(ctx.rel_op != null){

        }
        else if(ctx.primaryExpr() != null 
            && ctx.primaryExpr().operand() != null
            && ctx.primaryExpr().operand().operandName() != null){
            TerminalNode token = ctx.primaryExpr().operand().operandName().IDENTIFIER();
            Line line = new Line(table.size, Operations.id, token.getText(), null, ctx);
            table.add(line);
            // System.out.println(table);
        }
        return visitChildren(ctx);
    }

    public Integer visitShortVarDecl(GoParser.ShortVarDeclContext ctx){
        System.out.println("############  ShortVarDecl  ##################");
        System.out.println(ctx.getText());
        System.out.println("##############################");
        return visitChildren(ctx);
    }

    public Integer visitExpressionList(GoParser.ExpressionListContext ctx){
        System.out.println("############  ExpressionList  ##################");
        System.out.println(ctx.getText());
        System.out.println("##############################");
        return visitChildren(ctx);
    }

}
